﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InCom.Core.SyncInteractive
{
    using inCom.Logs;
    using InCom.SyncStatus;
    using InCom.Utilities;
    using InCom.Utilities.Pool;
    using InCom.Utilities.Protocol;
    /// <summary>
    /// 终端交互指令 数据发送缓冲区 incom-> incom.api
    /// </summary>
    public class SyncDataInteractiveSendBuffer : IPool
    {



        #region 构造函数与单例

        /// <summary>
        /// 构造函数
        /// </summary>
        protected SyncDataInteractiveSendBuffer()
        {
            //初始化池对像
            InitalizePool();
            //初始化发送数据线程
            TaskEx task = new TaskEx(SendToSyncPoint) { AutoReRun = true, StartTime = DateTime.Now, ThreadName = "SyncDataInteractiveSendBuffer ,从incom发送到其它数据同步节点的线程" };
            task.Start();

            ThreadManager.Instance.Add(task);
        }

        private static readonly SyncDataInteractiveSendBuffer instance = new SyncDataInteractiveSendBuffer();
        /// <summary>
        /// 数据同步与incom交互主要处理功能,静态访问单例
        /// </summary>
        public static SyncDataInteractiveSendBuffer Instance
        {
            get { return instance; }
        }

        #endregion

        private long sendCount = 0;
        /// <summary>
        /// 发送数据字节统计
        /// </summary>
        public long SendCount
        {
            get { return sendCount; }
        }

        /// <summary>
        /// 将需要发送的实时数据对像添加到发送队列缓冲区
        /// </summary>
        /// <param name="readdata">需要发送的实时数据对像</param>
        /// <param name="syncPoint">需要发送到的数据同步节点,null将发送到所有已知的incom.api节点</param>
        public void Push(BaseTcpProtocolEntity realdata, SyncPoint syncPoint)
        {
            //如果没有标识则加上标识
            if (string.IsNullOrEmpty(realdata.UserFlag))
            {
                realdata.UserFlag = "InCom," + Guid.NewGuid();
            }

            var item = Pop();
            item.Protocol = realdata;
            item.Client = syncPoint;
            //这种协议有可能没有终端号
            //item.TerminalCode = realdata.ter;
            lock (sendQueue)
            {
                //加入到发送队列缓冲区
                sendQueue.Enqueue(item);
            }
            //表示可以发送数据
            //hand.Set();
        }

        //异步handler
        private System.Threading.AutoResetEvent hand = new System.Threading.AutoResetEvent(false);

        /// <summary>
        /// 发送绥冲区的队列
        /// </summary>
        internal Queue<SyncCommandEntity> sendQueue = new Queue<SyncCommandEntity>(3000);


        #region 发送对像池
        /// <summary>
        /// 池队列
        /// </summary>
        protected Queue<SyncCommandEntity> poolQueue = new Queue<SyncCommandEntity>(3000);

        /// <summary>
        /// 获取一个对像
        /// </summary>
        /// <returns></returns>
        protected SyncCommandEntity Pop()
        {
            lock (poolQueue)
            {
                return poolQueue.Count > 0 ? poolQueue.Dequeue() : new SyncCommandEntity() { Pool = this };
            }
        }

        /// <summary>
        /// 还池
        /// </summary>
        /// <param name="bakcObject"></param>
        public void Push(object bakcObject)
        {
            SyncCommandEntity obj = (SyncCommandEntity)bakcObject;
            if(obj==null)
            {
                return;
            }
            obj.Protocol = null;
            obj.Client = null;
            obj.TerminalCode = 0;
            lock (poolQueue)
            {
                //还池
                poolQueue.Enqueue(obj);

            }

        }



        /// <summary>
        /// 初始化池
        /// </summary>
        protected void InitalizePool()
        {
            //初始化池对像
            System.Linq.Enumerable.Range(1, 200).ToList().ForEach((o) =>
                                                                      {
                                                                          poolQueue.Enqueue(new SyncCommandEntity() { Pool = this });
                                                                      });
        }

        #endregion


        /// <summary>
        /// 用于统计的记数器,
        /// </summary>
        /// <param name="obj"></param>
        protected void Statistical(SyncCommandEntity obj)
        {
            ///代码没有编写

        }



        /// <summary>
        /// 发送到数据同步节点
        /// </summary>
        private void SendToSyncPoint()
        {

            while (true)
            {
                try
                {
                    SendWorker();
                }
                catch (Exception ex)
                {
                    LogProvider.Create().Write(EventType.Warning, string.Format(" 方法SyncDataInteractiveSendBuffer.SendToSyncPoint(),出现末处理异常:{0}", ex.ToString()));
                }
                // hand.WaitOne();
            }
        }

        /// <summary>
        /// 循环执行的方法 
        /// </summary>
        private void SendWorker()
        {

            SyncCommandEntity obj = null;
            lock (sendQueue)
            {
                if(sendQueue.Count > 0)
                {
                    obj = sendQueue.Dequeue();
                }
            }
            if (obj == null)
            {
                System.Threading.Thread.Sleep(5);
                return;
            }

            //先转换为incom.api数据
            var apiProtocol = obj.Protocol;
            var parse = API.Protocols.PluginModulesManager.Instance.GetTcpParse(apiProtocol.MSGSEQ);
            //再进行数据转换
            if (parse != null)
            {
                byte[] sendBuff = parse.Create(apiProtocol);
                //节点是否可用,不可用则默认发向所有的incom.api
                if (obj.Client != null)
                {
                    //将数据发送到指令的 数据同步节点
                    SyncPointManager.Instance.Send(obj.Client, sendBuff);
                }
                else
                {
                    //终端上下线通知所有类型节点
                    if(apiProtocol.MSGSEQ ==(ushort)API.Protocols.APIProtocolType.TERMINAL_ONLINE
                        ||
                        apiProtocol.MSGSEQ ==(ushort)API.Protocols.APIProtocolType.TERMINAL_OFFLINE
                        )
                    {
                        SyncPointManager.Instance.Broadcast(sendBuff, SyncPointType.None);
                    }
                    else
                    {
                        //将数据发送到所有的,IncomAPI 数据同步节点
                        SyncPointManager.Instance.Broadcast(sendBuff, SyncPointType.InComAPI);

                    }
                }
                //增加数值
                System.Threading.Interlocked.Add(ref sendCount, sendBuff.Length);
                //进行发送统计
                Statistical(obj);
                //将使用过后的队列还池
                Push(obj);

            }
            else
            {
                LogProvider.Create().Write(EventType.Warning, string.Format("incom 指令数据发送到 incom.api 时出现问题, 未能将 incom.api  中的MSGSEQ:{0},找到合适的解析方法,  方法SyncDataInteractiveSendBuffer.SendToSyncPoint()", apiProtocol.MSGSEQ));
            }

            //if (sendQueue.Count == 0)
            //{
            //    System.Threading.Thread.Sleep(5);
            //}
        }


    }
}
